package com.pine.app.module.security.oauth.plugin.intercept;


import com.pine.app.module.security.core.common.SpringContextUtils;
import com.pine.app.module.security.oauth.plugin.DefaultProcessPluginChain;
import com.pine.app.module.security.oauth.plugin.Plugin;
import com.pine.app.module.security.oauth.plugin.ProcessPlugin;
import com.pine.app.module.security.oauth.plugin.ProcessPluginChain;
import lombok.extern.slf4j.Slf4j;
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;


/**
 * @author xiaoyuan
 * @create 2019/9/2 13:55
 **/
@Slf4j
public class PluginInterceptor implements MethodInterceptor {




    private ProcessPluginChain processPluginChain;

    public PluginInterceptor(){


    }

    private Long start;


    @Override
    public Object invoke(MethodInvocation invocation) throws Throwable {
        //执行延迟加载
        if(processPluginChain==null){
            processPluginChain = new DefaultProcessPluginChain();
            List<ProcessPlugin> observers = Collections.emptyList();
            Map<String, ProcessPlugin> beansOfType = SpringContextUtils.getBeanMap(ProcessPlugin.class);
            if (beansOfType != null) {
                observers =new ArrayList<>( beansOfType.values());
            }
            processPluginChain.attachAll(observers);
        }
        Method method = invocation.getMethod();
        Plugin plugin =   AnnotationUtils.findAnnotation(method, Plugin.class);
        start = System.currentTimeMillis();
        ServletRequestAttributes attributes =
                (ServletRequestAttributes) RequestContextHolder.currentRequestAttributes();
        HttpServletRequest request = attributes.getRequest();
        HttpServletResponse response = attributes.getResponse();
        Object result ;
        try{
            if(plugin.enabled()){
                processPluginChain.prepare(request,response,invocation,plugin);
            }
            RequestContextHolder.setRequestAttributes(attributes);
             result = invocation.proceed();
            if(plugin.enabled()){
                processPluginChain.complete(request,response,result,plugin);
            }
            RequestContextHolder.setRequestAttributes(attributes);
        }catch (Exception e){
            if(plugin.enabled()){
                processPluginChain.exception(request,response,e,plugin);
            }
            throw e;

        }
        return result;
    }

}
